//package com.bestcem.xm.txtanls.job;
//
//import com.bestcem.xm.common.core.constant.Constants;
//import com.bestcem.xm.common.core.domain.web.ServiceResult;
//import com.bestcem.xm.componet.redis.service.RedisService;
//import com.bestcem.xm.txtanls.dao.AnalysisProjectDao;
//import com.bestcem.xm.txtanls.entity.pojo.ProjectDO;
//import com.bestcem.xm.txtanls.enums.AnalysisStatusEnum;
//import com.bestcem.xm.txtanls.enums.TrainStatusEnum;
//import com.bestcem.xm.txtanls.job.config.TrainJobConfig;
//import com.bestcem.xm.txtanls.service.AsyncTaskService;
//import com.bestcem.xm.txtanls.util.AnalysisUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.quartz.Job;
//import org.quartz.JobExecutionContext;
//import org.redisson.api.RLock;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
//import org.springframework.stereotype.Component;
//import org.springframework.util.ObjectUtils;
//
//import javax.annotation.Resource;
//import java.util.Objects;
//import java.util.concurrent.TimeUnit;
//
///**
// * 实时训练
// *
// * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
// * @version v1.0
// * @date 2021/5/21 15:43
// */
//@Slf4j
//@Component
//@ConditionalOnBean(TrainJobConfig.class)
//public class CreatedTrainingJob implements Job {
//    private static final Logger EMAIL_LOG = LoggerFactory.getLogger("EmailErrorLog");
//
//    @Resource
//    private AnalysisProjectDao analysisProjectDao;
//    @Resource
//    private AsyncTaskService asyncTaskService;
//    @Resource
//    private AnalysisUtil analysisUtil;
//    @Resource
//    private TrainJobConfig trainJobConfig;
//    @Resource
//    private RedisService redisService;
//
//    @Override
//    public void execute(JobExecutionContext jobExecutionContext) {
//        if (log.isInfoEnabled()) {
//            log.info("[Txtanls] 实时训练定时任务开始");
//        }
//        String jobName = jobExecutionContext.getJobDetail().getKey().getName();
//        String projectId;
//
//        ProjectDO project = analysisProjectDao.findOneByStatus(AnalysisStatusEnum.CREATED.getIndex());
//        if (Objects.isNull(project)) {
//            if (log.isInfoEnabled()) {
//                log.info("[Txtanls] 实时训练定时任务无满足目标");
//            }
//            return;
//        }
//
//        projectId = project.getId();
//        // 获取锁
//        RLock lock = this.redisService.getLock(trainJobConfig.getTrainingJobLockKey(projectId));
//        if (lock.isLocked()) {
//            if (log.isInfoEnabled()) {
//                log.info("[Txtanls] {} 项目已在实时训练", projectId);
//            }
//            return;
//        }
//
//        // 加锁成功与否
//        boolean isLocked = false;
//        try {
//            // 加锁, 不自动释放
//            if (lock.tryLock(0L, TimeUnit.SECONDS)) {
//                isLocked = true;
//                // 训练
//                ServiceResult<Object> serviceResult = asyncTaskService.trainTask(project);
//                if (!serviceResult.isSuccess()) {
//                    ErrorHandler(projectId, jobName, serviceResult.getMsg(), null);
//                }
//            } else { // 加锁失败
//                if (log.isInfoEnabled()) {
//                    log.info("[Txtanls] {} 项目已在实时训练", projectId);
//                }
//            }
//        } catch (InterruptedException e) {
//            log.warn("[Txtanls] {} 项目实时训练获取锁被中断", projectId);
//        } catch (Exception e) {
//            if (!ObjectUtils.isEmpty(projectId)) {
//                ErrorHandler(projectId, jobName, e.getMessage(), e);
//            }
//        } finally {
//            if (isLocked) {
//                // 是否当前线程持有锁
//                if (lock.isHeldByCurrentThread()) {
//                    // 手动释放锁
//                    lock.unlock();
//                } else {
//                    log.error("[Txtanls] {} 项目实时训练锁持有对象转移", projectId);
//                }
//            }
//        }
//
//        if (log.isInfoEnabled()) {
//            log.info("[Txtanls] 实时训练定时任务完成; ProjectId: {}", projectId);
//        }
//    }
//
//    /**
//     * 训练任务失败处理
//     *
//     * @param projectId 项目id
//     * @param jobName   任务名
//     * @param errorMsg  错误信息
//     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
//     * @date 2021/7/5 11:17
//     */
//    private void ErrorHandler(String projectId, String jobName, String errorMsg, Exception e) {
//        // 更新项目状态
//        int failedUpdateResult = analysisUtil.updateProjectStatus(projectId, AnalysisStatusEnum.FAILED);
//        if (failedUpdateResult == 0) {
//            log.error("[Txtanls] {} 失败任务更新项目状态失败", projectId);
//        }
//        // 更新训练状态
//        int updateStateEndResult = analysisProjectDao.updateAnalysisProjectProgress(projectId, TrainStatusEnum.FINISHED, Constants.PROGRESS_FINISHED);
//        if (updateStateEndResult == 0) {
//            log.error("[Txtanls] {} 失败任务更新训练状态失败", projectId);
//        }
//        if (Objects.isNull(e)) {
//            log.error("[Txtanls] {}-{} 实时训练失败; ErrorMsg: {}", jobName, projectId, errorMsg);
//            EMAIL_LOG.error("[Txtanls] {}-{} 实时训练失败; ErrorMsg: {}", jobName, projectId, errorMsg);
//        } else {
//            log.error("[Txtanls] {}-{} 实时训练失败; ErrorMsg: {}", jobName, projectId, errorMsg, e);
//            EMAIL_LOG.error("[Txtanls] {}-{} 实时训练失败; ErrorMsg: {}", jobName, projectId, errorMsg, e);
//        }
//    }
//}
